package com.openlogic.common.logic.run;

import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;

import org.apache.commons.text.StringEscapeUtils;
import org.noear.solon.annotation.Component;
import org.noear.solon.core.event.AppBeanLoadEndEvent;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.googlecode.aviator.AviatorEvaluator;
import com.googlecode.aviator.Expression;
import com.openlogic.common.core.utils.DateUtils;
import com.openlogic.common.logic.constants.RuleConstants;
import com.openlogic.common.logic.node.enums.NodeExecEnums;
import com.openlogic.common.logic.node.factory.NodeExecFactory;
import com.openlogic.common.logic.utils.StackExceptionUtils;

import net.sf.json.JSONArray;
import net.sf.json.JSONObject;

/**
* @ClassName: ExecMatrixNewNodeHandler
* @Description: 评分卡节点运行执行器
* @author weiyongpeng
* @date 2024年7月17日 上午9:12:36
 */
@Component
public class ExecScoreCardNodeHandler extends ExecRuleHandler{
	
	private static final Logger logger = LoggerFactory.getLogger(ExecScoreCardNodeHandler.class);

	@Override
	public JSONObject typeRun(JSONArray resultArray1,JSONArray nodeArray,JSONArray lineArray,JSONObject inputjson,JSONArray areaArray,String areaFirst,String ruleId,StringBuffer reason,Map<String,Object> map) {
		JSONObject reJson = new JSONObject();
		logger.info("ScoreCardNewNode Begin Run Starting...");
		// 默认节点解析后的数据
		logger.info("typeRun=====" +  resultArray1.toString());
		reJson = recRunForNode(resultArray1,nodeArray,lineArray,inputjson,areaArray,areaFirst,ruleId,reason,map);	
		return reJson;
	}

	/**
	* 描述：迭代节点执行
	* @Title: recRunForDefault
	* @param resultArray1
	* @param nodeArray
	* @param lineArray
	* @param inputjson
	* @param areaArray
	* @param areaFirst
	* @param ruleId
	* @param reason
	* @param map
	* @return
	* @author weiyongpeng
	* @date  2024年7月17日 上午10:29:23
	 */
	@SuppressWarnings("rawtypes")
	@Override
	protected JSONObject recRunForNode(JSONArray resultArray1, JSONArray nodeArray, JSONArray lineArray,
			JSONObject inputjson, JSONArray areaArray, String areaFirst, String ruleId, StringBuffer reason,
			Map<String, Object> map) {
		Map<Object,Object> inParam = new HashMap<>();
		Map<Object,Object> outParam = new HashMap<>();
		for (Object ijo : inputjson.entrySet()){
	    	if(!((Map.Entry)ijo).getKey().toString().equals("everyNodeList") && !((Map.Entry)ijo).getKey().toString().equals("areaInfo") ) {
	    		inParam.put(((Map.Entry)ijo).getKey().toString().replaceAll("\"", ""), ((Map.Entry)ijo).getValue().toString().replaceAll("\"", ""));
	    	}
	    }
		// 开始执行时间
		Date startDate = DateUtils.getNowDate();
		String startExecuateTime = DateUtils.formatDate(startDate, DateUtils.YYYY_MM_DD_HH_MM_SS);
		// 异常信息
		String errorMsg = "";
		// 流程执行结束的json对象
		JSONObject reJson = new JSONObject();
		// 发生异常的时候返回的json对象
		JSONObject errorJson = new JSONObject();
		// 下一个可执行节点的json对象
		JSONObject nextResult = new JSONObject();
		
		try {
			//那么
			String successString = ((JSONObject)resultArray1.get(3)).get("success").toString();
			successString = StringEscapeUtils.unescapeXml(successString);
			
			JSONObject tmpObject = JSONObject.fromObject(successString);
			String str = tmpObject.get("scoreCardData").toString();
			str = StringEscapeUtils.unescapeXml(str);
			
			String resultStr = runAndGetResultForScoreCard(str,inputjson.toString(),reason);
			
			inputjson = JSONObject.fromObject(resultStr);
		} catch (Exception e) {
			errorMsg = StackExceptionUtils.getExceptionType(e).toString();
			logger.error("异常信息:{}",e.getMessage());
		}
		
		if (errorMsg == null || errorMsg.equals("")) {
			for (Object ijo : inputjson.entrySet()){
		    	if(!((Map.Entry)ijo).getKey().toString().equals("everyNodeList") && !((Map.Entry)ijo).getKey().toString().equals("areaInfo") ) {
		    		outParam.put(((Map.Entry)ijo).getKey().toString().replaceAll("\"", ""), ((Map.Entry)ijo).getValue().toString().replaceAll("\"", ""));
		    	}
		    }
			reJson = inputjson;
			if(resultArray1.get(2).equals("area")) {
				if(areaFirst.equals("")) {//判断是否是循环的第一个 节点
					areaFirst = resultArray1.getString(0);
					reJson.put("areaFirst", areaFirst);
				}
			}
			nextResult = runNextNode(resultArray1,nodeArray,lineArray,inputjson,areaArray,areaFirst,ruleId,0,reason,map,startDate,inParam,outParam);
			if(!nextResult.toString().equals("{}")) {
				return nextResult;
			}
		}else {
			Map<Object,Object> errorMap = new HashMap<>();
			errorMap.put("msg", errorMsg);
			errorJson = JSONObject.fromObject(errorMap);
			// 执行异常信息
			nextResult = runNextNodeThrow(resultArray1,nodeArray,lineArray,inputjson,areaArray,areaFirst,ruleId,0,reason,map,startDate,inParam,errorJson);
			if(!nextResult.toString().equals("{}")) {
				return nextResult;
			}
		}
		// 结束执行时间
		Date endDate = DateUtils.getNowDate();
		String endExecuateTime = DateUtils.formatDate(endDate, DateUtils.YYYY_MM_DD_HH_MM_SS);
		reJson.put("startExecTime", startExecuateTime);
		reJson.put("endExecTime", endExecuateTime);
		reJson.put("execTotalTimeMills", "耗时: "+(endDate.getTime() - startDate.getTime())+" 毫秒");
		reJson.put("execStatus", RuleConstants.NODE_EXEC_SUCCESS);
		return reJson;
	}
	
	@SuppressWarnings("unchecked")
	public String runAndGetResultForScoreCard(String str,String parmInfo, StringBuffer reason) {
		double scoreSum=0;
		JSONObject strJson = JSONObject.fromObject(str);
		String jiaquanadd = strJson.get("jiaquanadd").toString();
		String assParam = strJson.get("assParam").toString();
		JSONArray dataArray = new JSONArray();
		dataArray = JSONArray.fromObject(strJson.get("data"));
		String dataArrayStr = dataArray.toString();
		int rowNum = dataArray.size(); 
	    JSONObject inputjson = JSONObject.fromObject(parmInfo);
		inputjson = sortJson(inputjson);
		Map<String, Object> env = inputjson; 
		
		String trueRowList = "";
		dataArray = JSONArray.fromObject(dataArrayStr);
		for(int i=0;i<rowNum;i++) {
			JSONArray newDataArr = new JSONArray();
			newDataArr = dataArray.getJSONArray(i);
			JSONObject data = newDataArr.getJSONObject(1);
			if("9".equals(data.get("type"))) {
				String formula = "";
				boolean result=true;
//				formula  = getFormula(data);
				formula = data.get("hiddenValue") == null ? "" : data.getString("hiddenValue");
				String oldFormula = data.get("showValue") == null ? "" : data.getString("showValue");
				try {
					if (formula.contains("@")) {
						Set<String> sqlVars = extractStrings(formula);
						for (String sqlVar : sqlVars) {
							if (sqlVar.split("\\.").length >= 2) {
								// sql参数某个字段
								formula = selectRuleSqlParamResByAviator(inputjson, sqlVar, data, true, env);
							}else {
								// 单纯的sql参数
								formula = selectRuleSqlParamResByAviator(inputjson, sqlVar, data, false, env);
							}
						}
						Expression compile = AviatorEvaluator.compile(formula.replaceAll("\\@", ""), true);
						result = (Boolean)compile.execute(env);
					}else {
						result = (Boolean) AviatorEvaluator.execute(formula, env, true);
					}
				} catch (Exception e) {
					e.printStackTrace();
				}
				if(result) {
					reason.append("满足：");
					reason.append(oldFormula).append(",");
					JSONObject scoreData = newDataArr.getJSONObject(2);
					String hiddenValue = scoreData.get("hiddenValue").toString();
					
					String value1 = hiddenValue;
					if("0".equals(jiaquanadd)) {
						scoreSum=scoreSum+Double.parseDouble(value1);
					}else {
						JSONObject quanzhongData = newDataArr.getJSONObject(0);
						boolean isHidden = (boolean)quanzhongData.get("isHidden");
						if(isHidden) {
							String quanzhongStr = getQuanZhong(dataArray,i-1);
							scoreSum=scoreSum+Double.parseDouble(value1)*Double.parseDouble(quanzhongStr)/100;
						}else {
							String quanzhongStr = quanzhongData.get("quanzhong").toString();
							scoreSum=scoreSum+Double.parseDouble(value1)*Double.parseDouble(quanzhongStr)/100;
						}
						
					}
					if("".equals(trueRowList)) {
						trueRowList+=i;
					}else {
						trueRowList+=","+i;
					}
			    }
//				else {
//			    	reason.append("不满足任何条件");
//			    }
			}
		}
		inputjson.put(assParam, scoreSum);
		inputjson.put("trueRowList", trueRowList);

		return inputjson.toString();
	}
	
	public String getQuanZhong(JSONArray dataArray,int prevRow) {
		String quanzhongStr="";
		JSONArray newDataArr = new JSONArray();
		newDataArr = dataArray.getJSONArray(prevRow);
		JSONObject data = newDataArr.getJSONObject(0);
		if("8".equals(data.get("type"))) {
			if((boolean)data.get("isHidden")) {
				quanzhongStr = getQuanZhong(dataArray,prevRow-1);
			}else {
				quanzhongStr = data.get("quanzhong").toString();
			}
		}
		return quanzhongStr;
	}
	
	@Override
	public void onEvent(AppBeanLoadEndEvent event) throws Throwable {
		NodeExecFactory.register(NodeExecEnums.SCORECARD_NODE.getCode(), this);
	}

}
